//
//  LMKClient.h
//  LMK
//
//  Created by xuxinhua on 2020/2/6.
//  Copyright © 2020 xuxinhua. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "LMKCommonConstant.h"


@class LMKInitOptions;
@class LMKUser;
@class LMKToUser;
@class LMKMessage;
@class LMKEventResult;
@class LMKQueryHistoryParameter;
@class LMKUserState;
@class LMKChatSession;
@class LMKChatMessage;
@class LMKQuerySessionParameter;
@class LMKQueryHistoryMessageParameter;
@class LMKRoomSystemNotification;
@class LMKFile;
@class LMKDownloadParameter;
@class LMKRoom;
@class LMKUpdateRoom;
@class LMKRoomDetailResult;
@class LMKRoomDetail;
@class LMKUserJoinedRoom;
@class LMKRemoteHistoryMessageParmater;
@class LMKRoomMemberInfo;

typedef NS_ENUM(NSUInteger,LMKMatchType) {
    LMKMatchTypeLike = 0,//模糊匹配
    LMKMatchTypeMatch//完全匹配
};

typedef NS_ENUM(NSUInteger,LMKMemberStatus) {
    LMKMemberStatusInvalid = 0,//无效状态
    LMKMemberStatusNormal,//正常状态
    LMKMemberStatusAll//全部状态
};

/**
 初始化回调
 */
typedef void(^LMKInitBlock)(NSError *error, NSString *loginAccToken);
typedef void(^QueryHistoryMessageBlock)(NSError *error,NSArray<LMKMessage *> *messages);

/**
查询用户在线状态结果
@param error 错误信息
@param userState 状态信息
*/
typedef void(^QueryUserStateBlock)(NSError *error,LMKUserState *userState);


#pragma -mark 消息代理
@protocol LMKClientMessageDelegate <NSObject>

@optional
/**
 消息发送成功
 @param message 消息对象
 */
-(void)onLMKSendMessageSuccess:(LMKMessage *)message;

/**
 消息发送失败
 @param message 消息对象
 */
-(void)onLMKSendMessageFail:(LMKMessage *)message withError:(NSError *)error;

/**
 接收到消息
 @param messageList 消息对象集合
*/
-(void)onLMKReceiveMessage:(NSArray<LMKMessage *> *) messageList;

/**
 接收到补发消息
 @param messageList 消息对象集合
*/
-(void)onLMKReceiveReissueMessage:(NSArray<LMKMessage *> *) messageList;


/**
 接收到已读通知
 @param message 已读消息对象
*/
-(void)onLMKReceiveReadedSyncMessage:(LMKMessage *) message;

@end
#pragma -mark 用户代理
@protocol LMKClientUserDelegate <NSObject>

@optional
/**
 强制下线
 @param forceOfflineAccId 被强制下线用户的accId
 */
-(void)onLMKForceOfflineWithAccId:(NSString *)forceOfflineAccId;

@end

#pragma -mark 房间代理
@protocol LMKClientRoomDelegate <NSObject>

@optional
/**
 创建房间通知消息
 */
-(void)onLMKCreateRoom:(LMKRoomSystemNotification *)notification;

/**
 房间关闭通知
 */
-(void)onLMKCloseRoom:(LMKRoomSystemNotification *)notification;

/**
 用户加入房间通知成员消息
*/
-(void)onLMKJoinRoom:(LMKRoomSystemNotification *)notification;

/**
用户离开房间通知消息
*/
-(void)onLMKQuitRoom:(LMKRoomSystemNotification *)notification;

/**
 删除房间通知消息
 */
-(void)onLMKDeleteRoom:(LMKRoomSystemNotification *)notification;

/**
房间信息修改通知成员消息
*/
-(void)onLMKUpdateRoom:(LMKRoomSystemNotification *)notification;
@end

#pragma -mark 其它代理
@protocol LMKClientOtherDelegate <NSObject>

@optional
/**
 其它错误通知
 */
-(void)onLMKOtherError:(id)parameter;
/**
 通知刷新界面
 */
-(void)onLMKRefreshPage:(id)parameter;
@end

#pragma -mark 录音代理
@protocol LMKClientAudioDelegate <NSObject>

@optional
//录制音频完成
-(void)onLMKAudioRecorded:(NSString *)audioFilePath;

/**
 播放音频完成
 */
-(void)onLMKAudioRecordPlayed;

@end


@interface LMKClient : NSObject
/**
 消息代理
 */
@property (nonatomic,weak) id<LMKClientMessageDelegate> messageDelegate;
/**
 用户代理
 */
@property (nonatomic,weak) id<LMKClientUserDelegate> userDelegate;
/**
 其它代理
 */
@property (nonatomic,weak) id<LMKClientOtherDelegate> otherDelegate;
/**
 房间代理
 */
@property (nonatomic,weak) id<LMKClientRoomDelegate> roomDategate;
/**
 录音代理
 */
@property (nonatomic,weak) id<LMKClientAudioDelegate> recordAudioDelegate;


/**
    初始化imKit环境
    @param options  初始化imKit配置参数
    @param user     当前用户信息
    @param block    初始化回调
*/
-(void)LMKInitWithOptions:(LMKInitOptions *)options withUserInfo:(LMKUser *)user withBlock:(LMKInitBlock)block;

/**
 释放资源
 */
-(void)destroyLMK;

/**
 创建消息报文
 @param messageType 消息类型
 @param content 消息内容
 @param toUser 消息接收用户
 @param extend 消息扩展参数 json字符串
 @param quoteMessageSeq 引用消息序列
 @param atAccTokenArray @用户的acctoken数组
 @return 消息报文对象
 */
-(LMKMessage *)createMessageWithMessageType:(LMKMessageType)messageType
                                        content:(NSString *)content
                                         toUser:(LMKToUser *)toUser
                                         extend:(NSString *)extend
                                quoteMessageSeq:(NSString *)quoteMessageSeq
                                     atAccToken:(NSArray<NSString *> *)atAccTokenArray;
/**
 发送消息
 @param message 消息报文对象
 */
-(void)sendMessage:(LMKMessage *)message;
/**
 一条消息已读
 @param message 消息报文对象
 */
-(void)sendMessageRead:(LMKMessage *)message;

/**
 根据房间号和最后一条聊天时间批量已读
 @param roomId 房间号
 @param dataLine 最后一条聊天时间
 */
-(void)sendMessageReadByRoomId:(NSString *)roomId dataLine:(long)dataLine;

/**
 根据消息序列批量删除消息
 @param msgSeqs 消息序列数组
 @return 是否成功
 */
-(BOOL)deleteMessages:(NSArray<NSString *> *)msgSeqs;

/**
 根据房间号批量删除会话与会话下的消息
 @param roomIdArray 房间号数组
 @return 是否成功
 */
-(BOOL)deleteSessionWithRoomIdArray:(NSArray<NSString *> *)roomIdArray;

/**
 附件上传
 @param file 文件对象
 @param progressBlock 上传进度回调
 @param completionHandler 完成回调
 如果是图片上传完成会带上缩略图的thumbnailMd5，audio上传不会返回thumbnailMd5
 */
-(NSURLSessionDataTask *)uploadFormData:(LMKFile *)file
             progressBlock:(void(^)(NSProgress *uploadProgress))progressBlock
             completionHandler:(void(^)(NSError *error,NSString *fileCode,NSString *thumbnailMd5))completionHandler;
/**
 附件下载
 @param downloadParameter 下载参数对象
 @param progressBlock 下载进度回调
 @param completionHandler 完成回调
 */
-(NSURLSessionDownloadTask *)download:(LMKDownloadParameter *)downloadParameter
  progressBlock:(void (^)(NSProgress *progress))progressBlock
                    completionHandler:(void (^)(NSError *error, NSURL *filePath))completionHandler;

/**
 创建本地会话(创建房间后需要类似qq微信在会话表生成一条记录时调用)
 @param roomId 房间id
 */
-(BOOL)createLocalSession:(NSString *)roomId;

/**
 判断用户是否在线
 @param accId 用户accId
 @param block 结果回调
 */
-(void)queryUserStateWithAccId:(NSString *)accId
               withResultBlock:(QueryUserStateBlock)block;
/**
 查询会话列表(无分页)
 @param queryParameter 查询参数
 @return 会话列表
 */
-(NSArray<LMKChatSession *> *)querySessionList:(LMKQuerySessionParameter *)queryParameter;
/**
 查询某个会话下的历史消息(分页)
 @param queryParameter 查询参数
 @return 消息列表
 */
-(NSArray<LMKChatMessage *> *)queryHistoryMessageList:(LMKQueryHistoryMessageParameter *)queryParameter;

typedef void(^RemoteHistoryMessageBlock)(NSError *error,NSArray<LMKChatMessage *> *messageList);
/**
 查询服务器历史消息
 @param historyMessageParameter 查询条件
 @param block 历史消息回调
 */
-(void)queryRemoteHistoryMessage:(LMKRemoteHistoryMessageParmater *)historyMessageParameter widthResultBlock:(RemoteHistoryMessageBlock)block;

/**
 开始录制
 */
-(void)startAudio;
/**
 结束录制
 */
-(void)stopAudio;
/**
 获取画音量
 */
-(float)getAudioPower;
/**
 停止播放
 */
-(void)stopPlayAudio;
/**
 开始播放
 @param audioFilePath 音频文件路径(包含文件名称)
 */
-(void)playAudioWithFilePath:(NSString *)audioFilePath;
/**
 取消录制音频时删除本地音频文件
 @param filePath 音频文件路径(包含文件名称)
 */
-(void)removeAudioWithFilePath:(NSString *)filePath;


#pragma -mark 房间相关api
typedef void(^RoomIdBlock)(NSError *error,NSArray<LMKRoomDetail *> *roomDetails);
/**
 获取房间
 @param roomMembers 成员accId 非必须
 @param roomType 房间类型 非必须
 @param roomStatus 房间状态(只能是数字) 非必须
 @param matchType 匹配方式 LMKMatchTypeLike:模糊 LMKMatchTypeMatch:完全匹配
 @param block 房间信息回调
 */
-(void)getRooms:(NSArray<NSString *> *)roomMembers roomType:(NSString *)roomType roomStatus:(NSString *)roomStatus matchType:(LMKMatchType)matchType withResult:(RoomIdBlock)block;
/**
 获取或者创建房间
 @param roomInfo 房间信息
 @param block 房间信息回调
 */
-(void)getOrCreateRoom:(LMKRoom *)roomInfo withResult:(RoomIdBlock)block;

typedef void(^CreateRoomBlock)(NSError *error,LMKRoomDetail *roomId);
/**
创建房间
@param roomInfo 成员accId
@param block 创建房间回调
*/
-(void)createRoom:(LMKRoom *)roomInfo withResultBlock:(CreateRoomBlock)block;

typedef void(^RoomMemberListBlock)(NSError *error,NSArray<LMKRoomMemberInfo *> *roomMemberInfoArray);
/**
 查询服务器房间成员列表
 @param roomId 房间ID
 @param memberStatus 成员状态条件
 LMKMemberStatusInvalid 禁用（或者删除）
 LMKMemberStatusNormal 正常
 LMKMemberStatusAll 全部状态
 @param block 房间成员回调
 */
-(void)getRoomMemberList:(NSString *)roomId memberStatus:(LMKMemberStatus)memberStatus withResultBlock:(RoomMemberListBlock)block;

/**
查询本地房间成员列表
@param roomId 房间ID
@return 成员accId数组
*/
-(NSArray<NSString *> *)getLocalMemberList:(NSString *)roomId;


typedef void(^RoomDetailBlock)(NSError *error,LMKRoomDetailResult *roomDetail);
/**
 获取房间资料
 @param roomId 房间ID
 @param block 房间资料回调
 */
-(void)getRoomDetail:(NSString *)roomId withResultBlock:(RoomDetailBlock)block;

typedef void(^UpdateRoomBlock)(NSError *error,LMKRoomDetail *roomDetail);
/**
修改房间资料
@param roomInfo 房间信息
@param block 修改房间资料回调
*/
-(void)updateRoom:(LMKUpdateRoom *)roomInfo withResultBlock:(UpdateRoomBlock)block;

typedef void(^JoinRoomBlock)(NSError *error);
/**
 加入房间/拉人入房间
 @param roomId 房间ID
 @param roomMembers 房间成员accId数组
 @param block 加入房间回调
 */
-(void)joinRoom:(NSString *)roomId roomMembers:(NSArray<NSString *> *)roomMembers withResult:(JoinRoomBlock)block;

typedef void(^UserJoinedRoomListBlock)(NSError *error,NSArray<LMKUserJoinedRoom *> *roomMembers);
/**
 获取用户已加入的房间列表
 @param roomType 房间类型
 @param block 房间列表回调
 */
-(void)getUserJoinedRoomList:(NSString *)roomType withResultBlock:(UserJoinedRoomListBlock)block;


typedef void(^DeleteRoomMemberBlock)(NSError *error);
/**
 删除房间成员
 @param roomId 房间ID
 @param roomMembers 房间成员accId数组
 @param block  删除房间成员回调
 */
-(void)deleteRoomMember:(NSString *)roomId roomMembers:(NSArray<NSString *> *)roomMembers withResult:(DeleteRoomMemberBlock)block;

typedef void(^QuitRoomBlock)(NSError *error);
/**
 退出房间
 @param roomId 房间ID
 @param block  退出房间回调
 */
-(void)quitRoom:(NSString *)roomId withResultBlock:(QuitRoomBlock)block;

typedef void(^CloseRoomBlock)(NSError *error);
/**
 关闭房间
 @param roomId 房间ID
 @param block  关闭房间回调
 */
-(void)closeRoom:(NSString *)roomId withResultBlock:(CloseRoomBlock)block;

typedef void(^DeleteRoomBlock)(NSError *error);
/**
 删除服务器房间
 @param roomId 房间ID
 @param block  删除房间回调
 */
-(void)deleteRoom:(NSString *)roomId withResultBlock:(DeleteRoomBlock)block;

@end
